package org.lboot.flow.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.lboot.core.auth.AuthService;
import org.lboot.core.auth.anno.CheckRole;
import org.lboot.core.domain.ResponseDTO;
import org.lboot.core.exception.BusinessException;
import org.lboot.flow.FlowCtl;
import org.lboot.flow.constant.FlowWorkStatusConst;
import org.lboot.flow.module.assign.FlowTaskAssignService;
import org.lboot.flow.module.audit.FlowAudit;
import org.lboot.flow.module.audit.FlowAuditService;
import org.lboot.flow.module.define.FlowDefineService;
import org.lboot.flow.module.event.FlowCustomEventService;
import org.lboot.flow.module.process.FlowProcess;
import org.lboot.flow.module.process.FlowProcessService;
import org.lboot.flow.module.work.FlowWork;
import org.lboot.flow.module.work.FlowWorkService;
import org.lboot.flow.module.work.params.FlowStartParams;
import org.lboot.flow.module.work.params.FlowWorkQueryParams;
import org.lboot.jpa.utils.JpaDataUtil;
import org.lboot.starter.plugin.rsr.RsrTree;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author kindear
 * 流程实例控制类
 */
@Slf4j
@RestController
@RequestMapping("flow")
@Api(tags = "流程管理")
@AllArgsConstructor
@RsrTree("流程引擎")
public class FlowWorkController {
    AuthService authService;

    FlowWorkService flowWorkService;

    FlowDefineService defineService;

    FlowProcessService processService;

    FlowAuditService auditService;

    FlowTaskAssignService assignService;

    FlowCtl flowCtl;

    FlowCustomEventService eventService;

    @Resource
    ApplicationContext context;

    // 微服务接口调用支持
    @PostMapping("works/start")
    @ApiOperation(value = "流程发起")
    public ResponseDTO<Object> workStart(@Validated @RequestBody FlowStartParams startParams){

        // 获取流程定义
        return ResponseDTO.succData(
                flowCtl.startFlow(startParams)
        );
    }

    @GetMapping("works")
    @ApiOperation(value = "流程列表")
    public ResponseDTO<Object> workQueryList(FlowWorkQueryParams params){
        Pageable pageable = JpaDataUtil.buildPageable(params);
        FlowWork flowWork = new FlowWork();
        BeanUtil.copyProperties(params,flowWork, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        Example<FlowWork> example = Example.of(flowWork);
        return ResponseDTO.succData(
                flowWorkService.getAll(pageable,example)
        );
    }

    @GetMapping("works/{id}")
    @ApiOperation(value = "流程查询")
    public ResponseDTO<Object> workQuery(@PathVariable("id") String id){
        return ResponseDTO.succData(
                flowWorkService.getOneUnwrap(id)
        );
    }

    @GetMapping("works/{id}/audits")
    @ApiOperation(value = "流程审计记录")
    public ResponseDTO<Object> workAuditQueryList(@PathVariable("id") String id){
        FlowAudit audit = new FlowAudit();
        audit.setFlowWorkId(id);
        Example<FlowAudit> example = Example.of(audit);
        List<FlowAudit> audits = auditService.getExample(example);
        return ResponseDTO.succData(
                audits
        );
    }

    @GetMapping("works/{id}/processes")
    @ApiOperation(value = "流程流转记录")
    public ResponseDTO<Object> workProcessQueryList(@PathVariable("id") String id){
        FlowProcess process = new FlowProcess();
        process.setFlowWorkId(id);
        Example<FlowProcess> example = Example.of(process);
        List<FlowProcess> processes = processService.getExample(example);
        return ResponseDTO.succData(
                processes
        );
    }



    @PostMapping("works/{id}/down")
    @ApiOperation(value = "流程挂起")
    @CheckRole(orPerm = "flow:work:update")
    public ResponseDTO<Object> workDown(@PathVariable("id") String id){
        FlowWork flowWork = flowWorkService.getOneUnwrap(id);
        if (!FlowWorkStatusConst.IN_PROGRESS.equals(flowWork.getFlowWorkStatus())){
            throw new BusinessException(HttpStatus.FORBIDDEN,"只允许操作进行状态中流程实例");
        }
        flowWork.setStatus(0);
        return ResponseDTO.succData(
                flowWorkService.updateOne(flowWork)
        );
    }


    @PostMapping("works/{id}/up")
    @ApiOperation(value = "流程恢复")
    @CheckRole(orPerm = "flow:work:update")
    public ResponseDTO<Object> workUp(@PathVariable("id") String id){
        FlowWork flowWork = flowWorkService.getOneUnwrap(id);
        if (!FlowWorkStatusConst.IN_PROGRESS.equals(flowWork.getFlowWorkStatus())){
            throw new BusinessException(HttpStatus.FORBIDDEN,"只允许操作进行状态中流程实例");
        }
        flowWork.setStatus(1);
        return ResponseDTO.succData(
                flowWorkService.updateOne(flowWork)
        );
    }

    @DeleteMapping("works/{id}")
    @ApiOperation(value = "流程删除")
    @CheckRole(orPerm = "flow:work:delete")
    public ResponseDTO<Object> workDelete(@PathVariable("id") String id){
        flowCtl.deleteFlow(id);
        return ResponseDTO.succMsg("删除成功");
    }
}
